
package com.hlkj.pay.app.merchant.ext.impl.yeepay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.RoundingMode;
import java.util.LinkedHashMap;

import org.springframework.stereotype.Repository;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.YeePayScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.constant.YeePayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.handler.YeePayCommonParamsHandle;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;
import com.yeepay.yop.sdk.auth.credentials.PKICredentialsItem;
import com.yeepay.yop.sdk.auth.credentials.YopPKICredentials;
import com.yeepay.yop.sdk.security.CertTypeEnum;
import com.yeepay.yop.sdk.service.frontcashier.FrontcashierClient;
import com.yeepay.yop.sdk.service.frontcashier.FrontcashierClientBuilder;
import com.yeepay.yop.sdk.service.frontcashier.model.BankTransferPayAPIOfflineTransferResponseDTOResult;
import com.yeepay.yop.sdk.service.frontcashier.request.BankTransferPayRequest;
import com.yeepay.yop.sdk.service.frontcashier.response.BankTransferPayResponse;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import jodd.util.StringPool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 扫码统一下单
 *
 * @author HlpayTeam
 * @date 2024/11/18 13:07
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = YeePayExtConstant.BANKTRANSFER)
public class YeePayBankTransferPayOrderExtPt extends YeePaySceneCommonPayOrder implements YeePayScenePayOrderExtPt {

    private final YeePayCommonParamsHandle yeePayCommonParamsHandle;

    private static final FrontcashierClient api = FrontcashierClientBuilder.builder().build();

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {

        log.info("易宝 BANKTRANSFER 请求参数:{}", JsonUtils.toJsonString(channelPayOrderContext));
        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelPayOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        // 支付方式信息
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        // 额外参数信息
        PayOrderCommonParamReq.Extra extra = channelPayOrderContext.getExtra();
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();

        try {

            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);

            BankTransferPayRequest request = new BankTransferPayRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(YeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));
            // 失效时间
            request.setExpiredTime(DateUtils.dateToString(payOrderDO.getExpiredTime(), DatePattern.NORM_DATETIME_PATTERN));

            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }

            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setOrderAmount(NumberUtil.round(payOrderDO.getAmount(),2,RoundingMode.HALF_UP));
            request.setGoodsName(payOrderDO.getSubject());
            request.setNotifyUrl(channelPayOrderContext.getNotifyUrl());

            // 校验模式
            switch (PayEnums.CHECK_SCENE_TYPE.from(extra.getCheckType())){
                case REMARKCODE:
                    request.setCheckType("REMARKCODE");
                    break;
                default:
                    request.setCheckType("ACCOUNTNO");
                    break;
            }
            // 清算通知
            request.setCsUrl(domain + MerchantExtConstant.MERCHANT_ORDER_CS_CALLBACK_URL + payOrderDO.getChannelCode() + StringPool.SLASH + payOrderDO.getProviderCode());
            // 分账
            if(payOrderDO.getFundProcessType() != null){
                switch (PayOrderEnums.FUND_PROCESS_TYPE.from(payOrderDO.getFundProcessType())){
                    case DELAY_TIME:
                    case REAL_TIME:
                        request.setFundProcessType("DELAY_SETTLE");
                        break;
                    default:
                        request.setFundProcessType("REAL_TIME");
                        break;
                }
            }

            log.info("易宝提交BANKTRANSFER支付 请求参数:{}", JSONUtil.toJsonStr(request));
            BankTransferPayResponse response = api.bankTransferPay(request);
            BankTransferPayAPIOfflineTransferResponseDTOResult result = response.getResult();
            log.info("易宝提交BANKTRANSFER支付 返回参数:{}", JSONUtil.toJsonStr(result));

            if ("00000".equals(result.getCode())) {
                channelPayOrderContext.setPayDataType("data");
                // 结果顺序封装
                LinkedHashMap<String,String> data = new LinkedHashMap<>();
                data.put("receiveName",result.getReceiveName());
                data.put("receiveAccountNo",result.getReceiveAccountNo());
                data.put("accountName",result.getAccountName());
                data.put("areaInfo",result.getAreaInfo());
                data.put("remitRemarkCode",result.getRemitRemarkCode());
                channelPayOrderContext.setPayInfo(JSONUtil.toJsonStr(data));
            }else{
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark("易宝提交BANKTRANSFER支付 请求失败, fail: " + result.getMsg());
            }
        }catch (Exception e) {
            e.printStackTrace();
            channelPayOrderContext.setRemark("易宝提交BANKTRANSFER支付 请求失败, error: " + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }
}
